#include "SDL/SDL.h"

#include "video.h"
#include "videoext.h"
#include "object.h"
#include "plcnew.h"
#include "objectsystemNEWER.h"
#include "paletteNEWER.h"
#include "zoneNEWER.h"
#include "draw.h"
#include "plc.h"
#include "camera.h"
#include "sprite.h"
#include "sonic.h"
#include "joypad.h"
#include "collision.h"
#include "anim.h"
#include "hud.h"
#include "debug.h"
#include <stdio.h>



#define LONG(hi,lo) (hi<<16)+lo
#define HI(val) (val<<16)
#define LO(val) val
#define LONGTOWORD LEFTRADIXLONG
#define LEFTRADIXLONG(val) ((val & 0xFFFF0000) >> 16) 
#define SWAPWORD(val) (((val&0x00FF)<<8)+((val&0xFF00)>>8))


//extern zone currentZone;
extern object* player;
extern object* objects;
extern layerpalette backgroundpal;
extern layerpalette foregroundpal;

extern byte v_16x16[];
extern byte vRam[];
extern byte fgRam[];

word *vRamptr=(word*)vRam; 
word *fgRamptr=(word*)fgRam; 
extern long v_hscrolltablebuffer[];
byte *v_spritetablebuf=(byte*)getSpriteTableBuf();
extern byte v_sgfx_buffer[];
extern long v_screenposx;
extern long v_screenposy;
extern word v_lookshift;

extern word v_anglebuffer;
extern word FFFFF76A;

extern byte f_scorecount;
extern byte f_ringcount;
extern byte f_timecount;

//--the following variables/memory locations are buffered/copies transferred during a vblank..--
//--this is so the scroll engine can communicate with the drawing engine------------------------
extern word v_bgscroll1, v_bgscroll2, v_bgscroll3;
extern word scrollflagBuf1, scrollflagBuf2, scrollflagBuf3;

extern signed long FFFFF70C;   //bg layer sect 1 y pos
extern signed long FFFFF714;   //bg layer sect 2 y pos
extern signed long FFFFF708;   //bg layer sect 1 x pos
extern signed long FFFFF710;   //bg layer sect 2 x pos
extern signed long FFFFF718;   //bg layer sect 3 x pos
extern signed long FFFFF71C;   //bg layer sect 3 y pos
extern long screenposxBuf1, screenposyBuf1;
extern long FFFFFF18, FFFFFF1C, FFFFFF20, FFFFFF24, FFFFFF28, FFFFFF2C;

extern word v_scrposy_dup, FFFFF618;
extern word v_scrposx_dup, FFFFF61C;
extern word FFFFF61E, FFFFF620;
//-----------------------------------------------------------------------------------------------

bool keys[0xFFFF];
extern byte v_jpadhold1;
int mousex,mousey; 
bool mouseleft=false, mouseright=false;

bool quit=false;


byte v_zone;
    
void DrawScene();
SDL_Surface *screen;

extern long clock;
extern long delayTime;
extern long timeFrame;

int main( int argc, char** argv ) 
{ 
    initVideoExt();
    
    SDL_Event event;
    SDL_Init( SDL_INIT_VIDEO ); 
    screen = SDL_SetVideoMode( WINDOWWIDTH, WINDOWHEIGHT, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWPALETTE | SDL_ASYNCBLIT | SDL_HWACCEL );        
 
    pcPatterns();
    pcObjectMethods();
    pcLevelBounds();
    pcScrolling();
    pcSonic();
    pcStartLocations();

    v_zone=0;

    #define plcid_Main 0
    NewPLC(plcid_Main);    RunAllPLCs();    
           
    ClearPLC();
    //bsr.w	PaletteFadeOut
    //vvvv the value of '4' in AddPLC is actually the index of main patterns for GHZ, -should- be grabbed from LevelHeaders...
    AddPLC(4); 

    #define plcid_Main2 1
    //moveq	#plcid_Main2,d0       TODO: ALSO LOAD STANDARD PATTERNS                        
    //bsr.w	AddPLC		
    AddPLC(plcid_Main2);
    
    /* THEN HUGE LIST OF CLEAR/INITIALIZE LEVEL VARIABLES..., NOT NEEDED YET */
 
    /* CODE FOR LOAD THE PROPER SONIC PALETTE.. */

    /* CODE FOR PLAY THE PROPER BGM MUSIC */

    /* TITLE CARD LOOP (ALSO WHERE ALL PLCS FINALLY EXECUTED, INCLUDING THE RECENTLY CREATED FOR THE TITLE CARD PATTERNS) */
    RunAllPLCs();

    //jsr Hud_Base              ; load basic HUD gfx
    Hud_Base();

    //moveq	#palid_Sonic,d0
    //bsr.w	PalLoad1	; load Sonic's palette
    PalLoad1(palid_Sonic);

    LevelSizeLoad(v_zone);

    DeformLayers(v_zone);
    //bset	#2,(v_bgscroll1).w
    LevelDataLoad();
    LoadTilesFromStart();
    //jsr	FloorLog_Unk
    ColIndexLoad(v_zone);
    //bsr.w	LZWaterFeatures

    //move.b	#id_SonicPlayer,(v_objspace).w ; load Sonic object
    #define id_SonicPlayer 1
    objects[0].ID=1;
    
    //tst.w	(f_demo).w
    //bmi.s	Level_ChkDebug
    //move.b	#id_HUD,(v_objspace+$40).w ; load HUD object
    #define id_HUD 0x21
    objects[1].ID=id_HUD;
 
    /*
    Level_ChkDebug:
		tst.b	(f_debugcheat).w ; has debug cheat been entered?
		beq.s	Level_ChkWater	; if not, branch
		btst	#bitA,(v_jpadhold1).w ; is A button held?
		beq.s	Level_ChkWater	; if not, branch
		move.b	#1,(f_debugmode).w ; enable debug mode

    Level_ChkWater:
		move.w	#0,(v_jpadhold2).w
		move.w	#0,(v_jpadhold1).w
		cmpi.b	#id_LZ,(v_zone).w ; is level LZ?
		bne.s	Level_LoadObj	; if not, branch
		move.b	#id_WaterSurface,(v_objspace+$780).w ; load water surface object
		move.w	#$60,(v_objspace+$780+obX).w
		move.b	#id_WaterSurface,(v_objspace+$7C0).w
		move.w	#$120,(v_objspace+$7C0+obX).w
    */


    /* CODE FOR DEBUG/DEMO MODE ACTIVATE */

    //v_jpadhold2 = 0;    init joypad buffers
    //v_jpadhold1 = 0;

    //jsr	ObjPosLoad
    ExecuteObjects();
    BuildSprites();

    /* CODE FOR CLEAR A BUNCH OF LEVEL COUNTERS */
    //bsr.w	OscillateNumInit
    //move.b	#1,(f_scorecount).w ; update score counter
    //move.b	#1,(f_ringcount).w ; update rings counter
    //move.b	#1,(f_timecount).w ; update time counter
    f_scorecount = 1;      //enable
    f_ringcount = 1;       //game
    f_timecount = 1;       //counters

    /* .........*/
    
    
    /* LOAD DEMO MODE DATA */

    /* ADDITIONAL CODE FOR LOAD SEPARATE WATER PALETTES */
    
    /* CODE FOR DELAY TO ALLOW TITLE CARD TO DISPLAY */

    /* FADE IN TO LEVEL PALETTE COLORS */
    PaletteNoFade();

    /* CODE FOR SET TITLE CARD TO MOVE AWAY */

    #define plcid_Explode 2
    //moveq	#plcid_Explode,d0
    //jsr	(AddPLC).l	; load explosion gfx
    AddPLC(plcid_Explode);

    videoToSurfaceExt(screen);
    SDL_Flip(screen);
        
    clock = SDL_GetTicks();
    timeFrame = 0;
    
    #define singleFrame (1000/60)  //60 fps

    //While the user hasn't quit 
    while( quit == false ) 
    { 
        //bsr.w	PauseGame

	//move.b	#8,(v_vbla_routine).w

	//bsr.w	WaitForVBla

	//addq.w	#1,(v_framecount).w ; add 1 to level timer

	//bsr.w	MoveSonicInDemo

	//bsr.w	LZWaterFeatures
       
        //jsr	ExecuteObjects
        ExecuteObjects();

	//if Revision=0
	//else
	//tst.w   (f_restart).w
	//bne     GM_Level
	//endc
	//tst.w	(v_debuguse).w	; is debug mode being used?
	//bne.s	Level_DoScroll	; if yes, branch
	//cmpi.b	#6,(v_player+obRoutine).w ; has Sonic just died?
	//bhs.s	Level_SkipScroll ; if yes, branch
        
        //Level_DoScroll:
        //bsr.w	DeformLayers
        DeformLayers(v_zone);

	//Level_SkipScroll:
	//jsr	BuildSprites
        BuildSprites();

	//jsr	ObjPosLoad
        ObjPosLoad();

	//bsr.w	PaletteCycle
        PaletteCycle();
        
	//bsr.w	RunPLC
        RunAllPLCs();

	//bsr.w	OscillateNumDo

	//bsr.w	SynchroAnimate
        SynchroAnimate();

	//bsr.w	SignpostArtLoad

		/*cmpi.b	#id_Demo,(v_gamemode).w
		beq.s	Level_ChkDemo	; if mode is 8 (demo), branch
		if Revision=0
		tst.w	(f_restart).w	; is the level set to restart?
		bne.w	GM_Level	; if yes, branch
		else
		endc
		cmpi.b	#id_Level,(v_gamemode).w
		beq.w	Level_MainLoop	; if mode is $C (level), branch*/

        DrawScene();
        
        //While there's an event to handle 
        while( SDL_PollEvent( &event ) ) 
        { 
              //DisplaySprite(objects[0]);
                
               if( event.type == SDL_QUIT ) 
               { 
                   //Quit the program 
                   quit = true; 
               }
               if ( event.type == SDL_KEYDOWN )
               {
                   if ( event.key.keysym.sym == SDLK_ESCAPE ) { quit=true; }                   else { keys[event.key.keysym.sym]=true; }
               }
     	       if ( event.type == SDL_KEYUP )
	              keys[event.key.keysym.sym]=false;
	       if ( event.type == SDL_MOUSEMOTION )
	       {
                  mousex=event.motion.x;
                  mousey=event.motion.y;
                   
                  SLX_UpdateMouse(mousex, mousey);
               } 
               if ( event.type == SDL_MOUSEBUTTONDOWN )
	       {
                  mouseleft=(event.button.button==SDL_BUTTON_LEFT);
	          mouseright=(event.button.button==SDL_BUTTON_RIGHT);

                  SLX_UpdateMouseClick(mouseleft, mouseright);
               }
               if ( event.type == SDL_MOUSEBUTTONUP )
               {
	          mouseleft = (event.button.button!=SDL_BUTTON_LEFT);
	          mouseright = (event.button.button!=SDL_BUTTON_RIGHT);
                  
                  SLX_UpdateMouseClick(mouseleft, mouseright);
               }
        }

        timeFrame = SDL_GetTicks() - clock; 
        clock = SDL_GetTicks();
           
        delayTime = singleFrame - timeFrame;
        if (delayTime > 0) { SDL_Delay(delayTime); }
           
    }


    SDL_Quit(); 
    
    return 0; 
} 

void DrawScene()
{
     

     /* vblank code */
     UpdateVScrollFullscreen(LONG(v_scrposy_dup,FFFFF618));     

     ReadJoypads(keys);
     palToCRAM();
     UpdateSpriteTable(v_spritetablebuf);
     UpdateHScrollTable(v_hscrolltablebuffer);
     writeVRAM(v_sgfx_buffer,0x2E0,0xF000/*vram_sonic*/);

     scrollflagBuf1 = v_bgscroll1;
     scrollflagBuf2 = v_bgscroll2;
     scrollflagBuf3 = v_bgscroll3;
     screenposxBuf1 = v_screenposx;
     screenposyBuf1 = v_screenposy;
     FFFFFF18 = FFFFF708;
     FFFFFF1C = FFFFF70C;
     FFFFFF20 = FFFFF710;
     FFFFFF24 = FFFFF714;
     FFFFFF28 = FFFFF718;
     FFFFFF2C = FFFFF71C;

     LoadTilesAsYouMove();
     AnimateLevelGfx();
     HUD_Update();

     //bsr.w	sub_1642        for pattern load cues distributed over vblanks
     /*------------*/

     SLX_S1DebugInfo();   //not part of normal code, prints debug text of values to tiles
     
     videoToSurfaceExt(screen);
 
     SDL_Flip(screen);
}



